package controller;

import com.fasterxml.jackson.databind.ObjectMapper;
import constant_tools.FileTools;
import constant_tools.Final_Word;
import controller.result.Code;
import controller.result.Msg;
import controller.result.Result;
import domain.EntityFile;
import domain.VirtualFile;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import service.FileService;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;

import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.NoSuchAlgorithmException;
import java.sql.Timestamp;
import java.util.*;

@RestController
@RequestMapping("files")
@CrossOrigin
public class FileController {

    @Autowired
    private FileService fileService;

    //上传文件  
    @PostMapping
    public Result save(@ModelAttribute EntityFile entityFile) throws IOException, NoSuchAlgorithmException {

        //将上传的文件信息保存到数据库中
        VirtualFile virtualFile = new VirtualFile();
        virtualFile.setFname(entityFile.getUploadFile().getOriginalFilename());
        virtualFile.setDept(entityFile.getDept());
        virtualFile.setDescription(entityFile.getDescription());
        virtualFile.setSpeciality(entityFile.getSpeciality());
        virtualFile.setUploader(entityFile.getUploader());
        virtualFile.setUploadDateTime(new Timestamp(System.currentTimeMillis()));
        virtualFile.setMD5(FileTools.getMD5(entityFile.getUploadFile()));

        if(fileService.getByMD5(virtualFile.getMD5())){
            return new Result(Code.SAVE_ERR,null, Msg.FILE_EXIST);
        }

         //储存实体文件
        File dir = new File(Final_Word.SAVE_DIR+"\\"+entityFile.getDept()+"\\"+entityFile.getSpeciality());
        dir.mkdirs();
        File file = new File(dir, Objects.requireNonNull(entityFile.getUploadFile().getOriginalFilename()));
        entityFile.getUploadFile().transferTo(file);

        //判断是否保存成功并返回结果
        boolean flag= fileService.save(virtualFile);
        List<VirtualFile> list = fileService.getAll();
        return new Result(flag?Code.SAVE_OK:Code.SAVE_ERR,list);
    }


    //根据名字或文件描述获取文件
    @GetMapping("gbn/{fname}")
    public Result getByName_desc(@PathVariable String fname) {

        List<VirtualFile> virtualFile = fileService.getByName_desc(fname);

        return new Result(virtualFile!=null?Code.GET_OK:Code.GET_ERR,virtualFile,virtualFile!=null?Msg.FILE_GET_SUCCESS:Msg.FILE_NOT_EXIST);
    }



    //根据专业获取文件
    @GetMapping("gbs/{speciality}")
    public Result getBySpeciality(@PathVariable String speciality){
        List<VirtualFile> virtualFileList = fileService.getBySpeciality(speciality);
        return new Result(virtualFileList!=null?Code.GET_OK:Code.GET_ERR,virtualFileList,virtualFileList!=null?Msg.FILE_GET_SUCCESS:Msg.FILE_NOT_EXIST);
    }


    //文件预览
    @GetMapping("/getFileDetail/{fid}")
    public ResponseEntity<byte[]> getFileDetail(@PathVariable int fid, HttpServletRequest request) throws IOException {
        // 获取 PDF 文件的路径
        VirtualFile virtualFile = fileService.getById(fid);

        Path filePath = Paths.get(Final_Word.SAVE_DIR, virtualFile.getDept(), virtualFile.getSpeciality())
                .resolve(virtualFile.getFname())
                .normalize();

        // 读取文件内容
        byte[] fileContent = Files.readAllBytes(filePath);

        HttpHeaders headers = new HttpHeaders();

        if(virtualFile.getFname().endsWith("pdf"))
            headers.setContentType(MediaType.APPLICATION_PDF);
        else if(virtualFile.getFname().endsWith("jpg")||virtualFile.getFname().endsWith("jpeg"))
            headers.setContentType(MediaType.IMAGE_JPEG);
        else if(virtualFile.getFname().endsWith("png"))
            headers.setContentType(MediaType.IMAGE_PNG);
        else if(virtualFile.getFname().endsWith("txt"))
            headers.setContentType(MediaType.TEXT_PLAIN);
        else if(virtualFile.getFname().endsWith("md"))
            headers.setContentType(MediaType.TEXT_MARKDOWN);
        else if(virtualFile.getFname().endsWith("gif"))
            headers.setContentType(MediaType.IMAGE_GIF);
        else
            headers.setContentType(MediaType.TEXT_PLAIN);


        headers.setContentDispositionFormData("inline", virtualFile.getFname());

        return new ResponseEntity<>(fileContent, headers, HttpStatus.OK);
    }





    //获取所有文件
    @GetMapping
    public Result getAll() {

        List<VirtualFile> list = fileService.getAll();

        return new Result(list!=null?Code.GET_OK:Code.GET_ERR,list,list!=null?"get success":"data empty");
    }



    //文件下载
    @PostMapping("/download")
    public void downloadFiles(@RequestBody String ids, HttpServletResponse response) throws IOException {

        System.out.println(ids);
        ObjectMapper mapper = new ObjectMapper();
        Map<String,String> map = mapper.readValue(ids,Map.class);
        String [] IDS = map.get("ids").substring(1,map.get("ids").length()-1).split(",");

        List<File> fileList = new ArrayList<>();

        for(String id : IDS){
            VirtualFile virtualFile = fileService.getById(Integer.valueOf(id));
            File download_file = new File(Final_Word.SAVE_DIR+"\\"+virtualFile.getDept()+"\\"+virtualFile.getSpeciality()+"\\"+virtualFile.getFname());
            fileList.add(download_file);
        }

        File zip = new File("文件.zip");
        FileTools.filesTozip(fileList,zip);


        response.setHeader("Content-Disposition", "attachment; filename=" + zip.getName());
        InputStream in = null;
        try {
            in = new FileInputStream(zip);
            OutputStream out = response.getOutputStream();
            byte[] buff =new byte[1024];
            int index=0;

            //执行 写出操作
            while((index= in.read(buff))!= -1){
                out.write(buff, 0, index);
                out.flush();
            }

            out.close();
            in.close();

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }



}
